package com.dd.cloud.common.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.core.io.ClassPathResource;

import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Lx
 * @version 1.0
 */
public class AreaCodeUtil {
    private final Map<String, AreaCodeNode> areaMap = new HashMap<>(34);

    /**
     * 节点数据
     */
    public static class AreaCodeNode {
        private String code;

        private Map<String, AreaCodeNode> node;

        public String getCode() {
            return code;
        }

        public void setCode(String code) {
            this.code = code;
        }

        public Map<String, AreaCodeNode> getNode() {
            return node;
        }

        public void setNode(Map<String, AreaCodeNode> node) {
            this.node = node;
        }

        @Override
        public String toString() {
            return "AreaCodeNode{" + "code='" + code + '\'' + ", node=" + node + '}';
        }
    }

    private static class AreaCodeUtilHolder {
        private static final AreaCodeUtil INSTANCE = new AreaCodeUtil();
    }

    private AreaCodeUtil() {
        JSONArray array = jsonFileToJSONArray();
        recursion(array, areaMap);
        System.out.println("===============>areaMap:\n");
    }

    private void recursion(JSONArray arr, Map<String, AreaCodeNode> map) {
        for (int i = 0; i < arr.size(); i++) {
            JSONObject obj = arr.getJSONObject(i);
            AreaCodeNode node = new AreaCodeNode();
            node.setCode(obj.getString("value"));
            if (obj.containsKey("children")) {
                node.setNode(new HashMap<>(34));
                recursion(obj.getJSONArray("children"), node.getNode());
            }
            map.put(obj.getString("label"), node);
        }
    }

    private JSONArray jsonFileToJSONArray() {
        try {
            ClassPathResource resource = new ClassPathResource("template/areaCode.json");
            InputStreamReader inputStream = new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8);
            StringBuilder sb = new StringBuilder();
            try {
                char[] chars = new char[1024];
                int len;
                while ((len = inputStream.read(chars)) != -1) {
                    sb.append(chars, 0, len);
                }
                inputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("===============>jsonString:\n" + sb);
            return JSON.parseArray(sb.toString());
        } catch (IOException e) {
            e.printStackTrace();
            return new JSONArray();
        }
    }

    /**
     * 查询省市区代码 通过详细地址
     *
     * @param address 北京市市辖区东城区某某街道
     * @return "110000,110100,110101"
     */
    public String getProvinceCityDistrictCode(String address) {
        AddrUtils.AddrEntity addrEntity = AddrUtils.getAddrEntity(address);
        if (addrEntity.getFlag() == 0) {
            return "";
        }
        return getProvinceCityDistrictCode(addrEntity.getProvince(), addrEntity.getCity(), addrEntity.getDistrict(), ",");
    }

    /**
     * 查询省市区代码
     * 不支持单查市和区 支持单查省 需要单查区 需要传参省市区 如:北京市,市辖区,东城区 返回"110000,110100,110101" 第二个,后面110101区代码
     *
     * @param province 北京市
     * @param city     市辖区
     * @param district 东城区
     * @return "110000,110100,110101"
     */
    public String getProvinceCityDistrictCode(String province, String city, String district) {
        return getProvinceCityDistrictCode(province, city, district, ",");
    }

    /**
     * 查询省市区代码
     * 不支持单查市和区 支持单查省 需要单查区 需要传参省市区 如:北京市,市辖区,东城区 返回"110000,110100,110101" 第二个,后面110101区代码
     *
     * @param province 北京市
     * @param city     市辖区
     * @param district 东城区
     * @param split    ,
     * @return "110000,110100,110101"
     */
    public String getProvinceCityDistrictCode(String province, String city, String district, String split) {
        String code = "";
        if (province != null) {
            AreaCodeNode node = areaMap.get(province);
            if (node != null) {
                code = node.getCode();
                if (city != null) {
                    node = node.getNode().get(city);
                    if (node != null) {
                        code += split + node.getCode();
                        if (district != null) {
                            node = node.getNode().get(district);
                            code += split + node.getCode();
                        }
                    }
                }
            }
        }
        return code;
    }

    public static AreaCodeUtil getInstance() {
        return AreaCodeUtilHolder.INSTANCE;
    }
}
